﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using WindowsFormsAero;
using BGShell.Configuration;

namespace BGShell.Controls
{
    [System.ComponentModel.DesignerCategory("Code")]
    internal sealed class BGShellTabControl : AeroTabControl
    {
        private bool _openingNewTab;

        public BGShellTabControl()
        {
            CausesValidation = false;
            HideSingleTab = true;

            Margin = Padding.Empty;
            Padding = Padding.Empty;
        }

        #region LastTabClosed

        private static readonly object EventLastTabClosed = new object();

        public event EventHandler LastTabClosed
        {
            add { Events.AddHandler(EventLastTabClosed, value); }
            remove { Events.RemoveHandler(EventLastTabClosed, value); }
        }

        private void OnLastTabClosed(EventArgs e)
        {
            var handler = Events[EventLastTabClosed] as EventHandler;

            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        #region Text

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override string Text
        {
            get
            {
                if (SelectedTab != null)
                {
                    return SelectedTab.Text;
                }

                return string.Empty;
            }
            set
            {
                throw new NotSupportedException();
            }
        }

        #endregion

        public BGShellTabPage OpenTab()
        {
            return OpenTab(null);
        }

        public BGShellTabPage OpenTab(Type tabType)
        {
            if (tabType == null)
            {
                tabType = BGShellApplication.Current.AddInManager.DefaultTabType;
            }

            if (tabType != null)
            {
                var page = (BGShellTabPage)Activator.CreateInstance(tabType);

                page.IsBackgroundWindow = IsBackgroundWindow;
                page.OpenAsync();
                
                _openingNewTab = true;

                try
                {
                    TabPages.Add(page);
                    SelectedTab = page;
                }
                finally
                {
                    _openingNewTab = false;
                }

                return page;
            }

            return null;
        }

        public void CloseSelectedTab()
        {
            CloseTab(SelectedTab);
        }

        protected override void OnCloseButtonClick(AeroTabPageEventArgs e)
        {
            CloseTab(e.Page);

            base.OnCloseButtonClick(e);
        }

        protected override void OnNewTabButtonClick(EventArgs e)
        {
            OpenTab();

            base.OnNewTabButtonClick(e);
        }

        protected override void OnSelectedTabChanged(EventArgs e)
        {
            base.OnSelectedTabChanged(e);

            if (SelectedTab != null)
            {
                SelectedTab.TextChanged += InvokeTextChanged;
            }

            if (!_openingNewTab || !string.IsNullOrEmpty(SelectedTab.Text))
            {
                OnTextChanged(EventArgs.Empty);
            }
        }

        protected override void OnSelectedTabChanging(CancelEventArgs e)
        {
            base.OnSelectedTabChanging(e);

            if (!e.Cancel)
            {
                if (SelectedTab != null)
                {
                    SelectedTab.TextChanged -= InvokeTextChanged;
                }
            }
        }

        protected override void OnControlRemoved(ControlEventArgs e)
        {
            base.OnControlRemoved(e);

            if (TabPages.Count == 0)
            {
                OnLastTabClosed(EventArgs.Empty);
            }
        }

        internal bool IsBackgroundWindow
        {
            get;
            set;
        }

        internal int LastExitCode
        {
            get;
            set;
        }

        private void CloseTab(AeroTabPage page)
        {
            var bgPage = page as BGShellTabPage;

            if (bgPage != null)
            {
                bgPage.CloseAsync();
            }
            else if (page != null)
            {
                TabPages.Remove(page);
            }
        }

        private void InvokeTextChanged(object sender, EventArgs e)
        {
            OnTextChanged(e);
        }
    }
}
